package utils

import (
	"fmt"
	"log"
	"path"
	"runtime"
)

type ILogger interface {
	Debug(v ...interface{})
	Info(v ...interface{})
	Err(v ...interface{})
	Warn(v ...interface{})
	Debugf(format string, v ...interface{})
	Infof(format string, v ...interface{})
	Errf(format string, v ...interface{})
	Warnf(format string, v ...interface{})
	DebugTypef(typestr string, format string, args ...interface{})
	WarnTypef(typestr string, format string, args ...interface{})
	ErrTypef(typestr string, format string, args ...interface{})
	InfoTypef(typestr string, format string, args ...interface{})
	Msgf(typestr string, lvl LogLevel, callskip int, format string, args ...interface{})
	Close()
}

type DefaultLogger struct {
}

func NewDefaultLogger() *DefaultLogger {
	return &DefaultLogger{}
}

func GetCallerInfo(skip int) string {
	_, fn, lineno, ok := runtime.Caller(skip + 1)
	if ok {
		// return fmt.Sprintf("[%s:%.4d]", runtime.FuncForPC(pc).Name(), lineno)

		return fmt.Sprintf("[%s:%.4d]", path.Base(fn), lineno)
	} else {
		return ""
	}
}

func getSrc() string {
	_, fn, lineno, ok := runtime.Caller(2)
	if ok {
		// return fmt.Sprintf("[%s:%.4d]", runtime.FuncForPC(pc).Name(), lineno)

		return fmt.Sprintf(" (%s:%.4d)", path.Base(fn), lineno)
	} else {
		return ""
	}
}

func (this *DefaultLogger) Debug(v ...interface{}) {
	log.Print("[debug]", fmt.Sprint(v...), getSrc())
}

func (this *DefaultLogger) Info(v ...interface{}) {
	log.Print("[info]", fmt.Sprint(v...), getSrc())
}

func (this *DefaultLogger) Err(v ...interface{}) {
	log.Print("[err]", fmt.Sprint(v...), getSrc())
}

func (this *DefaultLogger) Warn(v ...interface{}) {
	log.Print("[Warn]", fmt.Sprint(v...), getSrc())
}

func (this *DefaultLogger) Debugf(format string, v ...interface{}) {
	log.Print("[debug]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) Infof(format string, v ...interface{}) {
	log.Print("[info]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) Errf(format string, v ...interface{}) {
	log.Print("[err]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) Warnf(format string, v ...interface{}) {
	log.Print("[warn]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) DebugTypef(typestr, format string, v ...interface{}) {
	log.Print("[debug]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) InfoTypef(typestr, format string, v ...interface{}) {
	log.Print("[info]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) ErrTypef(typestr, format string, v ...interface{}) {
	log.Print("[err]", fmt.Sprintf(format, v...), getSrc())
}

func (this *DefaultLogger) WarnTypef(typestr, format string, v ...interface{}) {
	log.Print(getSrc(), "[warn]", fmt.Sprintf(format, v...))
}

func (this *DefaultLogger) Msgf(typestr string, lvl LogLevel, callskip int, format string, args ...interface{}) {
	log.Print(GetCallerInfo(callskip+1), logLevelStrings[lvl], fmt.Sprintf(format, args...))
}

func (this *DefaultLogger) Close() {

}
